package com.gitee.wsl.time.schedule.cron


import com.gitee.wsl.time.schedule.AbstractTimeScheduler
import com.gitee.wsl.time.schedule.TimeScheduler
import com.gitee.wsl.time.schedule.ScheduleException
import kotlin.time.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlin.time.ExperimentalTime

data class CronDateTimeScheduler internal constructor(
    internal val cronDateTime: CronDateTime
) :  AbstractTimeScheduler() {
    /**
     * @return Near date using [cronDateTimes] list and getting the [Iterable.minByOrNull] one
     *
     * @see toNearDateTime
     */
    @OptIn(ExperimentalTime::class)
    override fun next(
        createdAtInstant: Instant,
        currentInstant: Instant,
        zoneId: TimeZone,
    ): Result<Instant> {
        val baseDate: LocalDateTime = currentInstant.toLocalDateTime(zoneId)
        val nextDate: LocalDateTime = cronDateTime.toNearDateTime(baseDate)?: return Result.failure(ScheduleException(cronDateTime.toString()))
        return Result.success(nextDate.toInstant(zoneId))
    }

}

internal fun mergeCronDateTimeSchedulers(
    schedulers: List<CronDateTimeScheduler>
): CronDateTimeScheduler = CronDateTimeScheduler(
    schedulers.map { it.cronDateTime }.merge()
)

fun TimeScheduler.Companion.create(vararg schedulers:CronDateTime) = mergeCronDateTimeSchedulers(
    schedulers.map { CronDateTimeScheduler(it) }
)

